package com.yunji.cabinet.business;

import com.google.common.base.Optional;
import com.yunji.cabinet.bo.BindCodeRemoteBO;
import com.yunji.cabinet.bo.BindCodeSelectQueryBO;
import com.yunji.cabinet.bo.CabinetSelectQueryBo;
import com.yunji.cabinet.device.DeviceAssert;
import com.yunji.cabinet.device.DeviceConvert;
import com.yunji.cabinet.device.DeviceValidate;
import com.yunji.cabinet.domain.DeviceBindDO;
import com.yunji.cabinet.domain.DeviceEventDO;
import com.yunji.cabinet.dto.CabinetActivateDTO;
import com.yunji.cabinet.dto.DeviceBindDTO;
import com.yunji.cabinet.engine.CabinetInitData;
import com.yunji.cabinet.params.DeviceEventParam;
import com.yunji.cabinet.service.IBindCodeService;
import com.yunji.cabinet.service.ICabinetService;
import com.yunji.cabinet.service.impl.BindCodeLogsService;
import com.yunji.cabinet.service.impl.DeviceService;
import com.yunji.cabinet.vo.CodeUrlVO;
import com.yunji.cabinet.vo.DeviceEventVO;
import com.yunji.common.exception.ServiceException;
import com.yunji.common.exception.device.DeviceErrorEnum;
import com.yunji.common.exception.device.DeviceException;
import com.yunji.common.utils.Pair;
import com.yunji.common.utils.RandomUtils;
import com.yunji.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author : peter-zhu
 * @date : 2025/1/14 20:11
 * @description : TODO
 */
@Slf4j
@Component
public class DeviceBusiness {
    @Resource
    IBindCodeService bindCodeService;

    @Resource
    BindCodeLogsService bindCodeLogsService;

    @Resource
    ICabinetService cabinetService;

    @Resource
    private DeviceService deviceService;

    private static final String URL = "https://hge.lcllq.com?code=";

    /**
     * @param nums 指定数量
     * @Title generateQRCode
     * @Desc 生成指定数量二维码地址
     * @Date 2024-06-07 13:52:05.060
     */
    public List<CodeUrlVO> generateQRCode(int nums) {
        List<CodeUrlVO> list = new ArrayList<>();
        for (int i = 0; i < nums; i++) {
            //放编码规则
            String uuid = RandomUtils.nextCode();
            CodeUrlVO codeUrlVO = new CodeUrlVO(URL + uuid);
            list.add(codeUrlVO);
        }
        return list;
    }

    /**
     * @param dto 绑定参数
     * @Title bindQRCodeChip
     * @Desc 绑定二维码和芯片
     * @Date 2024-06-07 13:56:12.068
     */
    @Transactional
    public void bindQRCodeChip(DeviceBindDTO dto) {
        boolean b1 = bindCodeService.removeByImeiOrQrCode(new BindCodeRemoteBO(dto.getImei(), dto.getQrCode()));
        if (b1)
            bindCodeLogsService.unbindLog(dto);
        boolean b = bindCodeService.create(new DeviceBindDO(dto.getImei(), dto.getQrCode(), dto.getSn()));
        if (b)
            bindCodeLogsService.bindLog(dto);
        else
            throw new DeviceException(DeviceErrorEnum.CHECKED_212507, dto);
    }

    public String getImeiByQrCode(String qrCode) {
        DeviceBindDO bind = bindCodeService.select(BindCodeSelectQueryBO.builder().qrCode(qrCode).build());
        String imei = Optional.fromNullable(bind).transform(DeviceBindDO::getImei).orNull();
        if (StringUtils.isEmpty(imei))
            throw new DeviceException(DeviceErrorEnum.CHECKED_212503, bind);
        return imei;
    }

    /**
     * @param dto 创建货柜
     * @return boolean 处理结果
     * @Title enableCabinet
     * @Date 2024-06-08 16:46:09.230
     */
    @Transactional
    public boolean createCabinet(CabinetActivateDTO dto) {
        DeviceBindDO bind = bindCodeService.select(BindCodeSelectQueryBO.builder().qrCode(dto.getQrCode()).build());
        DeviceValidate.bindNonNull(bind);
        DeviceAssert.isTrue(!cabinetService.exist(CabinetSelectQueryBo.builder().chipImei(bind.getImei()).qrcode(bind.getQrCode()).build()),
                DeviceErrorEnum.CHECKED_212508, bind.getImei());
        bind.setBindStatus(1);
        boolean flag = bindCodeService.update(bind);
        if (flag)
            flag = cabinetService.create(CabinetInitData.initByDevice(bind, dto.getTypeCode()));
        else
            throw new ServiceException("添加容器失败");
        return flag;
    }

    public Pair<String, String> getCmdJsonString(Long eventId) {
        DeviceEventDO eventById = deviceService.getEventById(eventId);
        return new Pair<>(eventById.getBeforeCmd(), eventById.getAfterCmd());
    }


    /**
     * @return List<CabinetRecords> 操作日志记录列表
     * @Title search
     * @Date 2024-06-09 22:19:55.952
     */
    public List<DeviceEventVO> list(DeviceEventParam param) {
        List<DeviceEventDO> search = deviceService.search(param);
        return search.stream().map(DeviceConvert::domain2VO).collect(Collectors.toList());
    }


}